iT邦幫忙

2026 iThome 鐵人賽

0
Build on Google AI

把Google AI當夥伴打造個人高效Coding工作流系列 第 9 篇

第九天String不可變性與字串池

  • 分享至 

  • xImage
  •  

一、 字串池與儲存位置

  • 字面量(String s = "abc"):
    優先從String Pool複用既有物件;若無則在池中建立並返回,因此相同字面量的 == 結果為true。
  • new String("abc"):
    無論池中有無相同字串,強制在一般Heap區開闢新物件,==比對結果必為false。
  • 字串比較鐵律:
    比對字串內容一律使用.equals(),絕不能用==。
  • 架構演進:
    JDK 7起將字串池從PermGen移至Java一般Heap區,避免因大量動態字串導致PermGen OOM,並讓字串能正常被GC回收。

二、 不可變性三大防線與價值

  • 防線構建:
  1. 類別標記為final(防繼承篡改)。
  2. 底層陣列宣告為private final(外部不可見、門牌不可換)。
  3. 無公開修改方法(所有轉換操作如substring、replace皆返回全新String 物件)。
  • 三大架構價值:
  1. 字串池共享安全:防止修改單一變數時污染其他共享該字串的變數。
  2. 天然線程安全:多執行緒間無鎖共享,完全消除併發衝突。
  3. 快取hashCode:字串內容不變,雜湊值計算一次後永久快取,大幅提升作為HashMap/HashSet Key時的查找效率。

三、 拼接效能災難:為什麼嚴禁迴圈使用+?

  • 編譯器行為:
    在執行期動態迴圈中,每次+=底層都會隱式建立一個新的StringBuilder並呼叫.toString()。
  • 效能瓶頸:
    迴圈執行 $N$ 次會瞬間在Heap產生 $2N$ 個短命物件,造成Eden區快速被塞滿,頻繁引發Minor/Full GC,導致CPU飆高與系統停頓。

四、 StringBuilder運作與擴容機制

  • 容器選擇:單執行緒拼接一律使用StringBuilder;多執行緒併發安全才考慮 StringBuffer。
  • 預設容量:無參數建構子預設容量為16個字元。
  • 擴容公式:當空間不足時,新容量計算為舊容量×2+2。
  • 效能建議:底層擴容依賴Arrays.copyOf()進行整塊連續記憶體複製與搬遷,大量拼接時務必預先指定容量,避免重複擴容拷貝的成本。

上一篇
第八天常數與靜態的架構規範——記憶體生命週期與單例模式的三種安全寫法
下一篇
第十天例外架構體系Checked vs Unchecked、資源洩漏防禦與自訂業務例外封裝
系列文
把Google AI當夥伴打造個人高效Coding工作流 共 13 篇
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言